package com.qzw.common.util;

import com.qzw.common.api.base.BaseModel;
import com.qzw.common.service.BaseEntity;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;

/**
 * @author ：quziwei
 * @date ：Created in 2020/6/1 2:17 下午
 * @description：反射工具包
 */
public class ReflectUtils<M extends BaseModel, E extends BaseEntity> {


    public M entity2model(E e, M m) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class entity = e.getClass();
        Class model = m.getClass();
        Object o1 = entity.newInstance();
        Object o2 = model.newInstance();
        for (Field eField : entity.getDeclaredFields()) {
            if (!ObjectUtils.isEmpty(eField)) {
                String name = eField.getName();
                Method method = null;
                method = entity.getMethod(toGetter(name));
                o1 = method.invoke(e, null);
                setValue(o2,model,name,model.getDeclaredField(name).getType(),o1);
            }
        }

        return (M) o2;
    }

    public E model2entity(M m, E e) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class entity = e.getClass();
        Class model = m.getClass();
        Object o1 = entity.newInstance();
        Object o2 = model.newInstance();
        for (Field eField : model.getDeclaredFields()) {
            if (!ObjectUtils.isEmpty(eField)) {
                String name = eField.getName();
                Method method = null;
                method = model.getMethod(toGetter(name));
                o2 = method.invoke(m, null);
                setValue(o1,entity,name,entity.getDeclaredField(name).getType(),o2);
            }else {
                continue;
            }
        }
        return (E) o1;
    }

    public static String toGetter(String fieldname) {

        if (fieldname == null || fieldname.length() == 0) {
            return null;
        }

        /* If the second char is upper, make 'get' + field name as getter name. For example, eBlog -> geteBlog */
        if (fieldname.length() > 2) {
            String second = fieldname.substring(1, 2);
            if (second.equals(second.toUpperCase())) {
                return new StringBuffer("get").append(fieldname).toString();
            }
        }

        /* Common situation */
        fieldname = new StringBuffer("get").append(fieldname.substring(0, 1).toUpperCase())
                .append(fieldname.substring(1)).toString();

        return fieldname;
    }

    public static String toSetter(String fieldname) {

        if (fieldname == null || fieldname.length() == 0) {
            return null;
        }

        /* If the second char is upper, make 'get' + field name as getter name. For example, eBlog -> geteBlog */
        if (fieldname.length() > 2) {
            String second = fieldname.substring(1, 2);
            if (second.equals(second.toUpperCase())) {
                return new StringBuffer("set").append(fieldname).toString();
            }
        }

        /* Common situation */
        fieldname = new StringBuffer("set").append(fieldname.substring(0, 1).toUpperCase())
                .append(fieldname.substring(1)).toString();

        return fieldname;
    }


    public static void setValue(Object obj, Class<?> clazz, String filedName, Class<?> typeClass, Object value) {
        filedName = removeLine(filedName);
        String methodName = "set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
        try {
            Method method = clazz.getDeclaredMethod(methodName, new Class[]{typeClass});
            method.invoke(obj, new Object[]{getClassTypeValue(typeClass, value)});
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    private static Object getClassTypeValue(Class<?> typeClass, Object value) {
        if (typeClass == int.class || value instanceof Integer) {
            if (null == value) {
                return 0;
            }
            return value;
        } else if (typeClass == short.class) {
            if (null == value) {
                return 0;
            }
            return value;
        } else if (typeClass == byte.class) {
            if (null == value) {
                return 0;
            }
            return value;
        } else if (typeClass == double.class) {
            if (null == value) {
                return 0;
            }
            return value;
        } else if (typeClass == long.class) {
            if (null == value) {

                return 0;
            }
            return value;
        } else if (typeClass == String.class) {
            if (null == value) {
                return "";
            }
            return value;
        } else if (typeClass == boolean.class) {
            if (null == value) {
                return true;
            }
            return value;
        } else if (typeClass == BigDecimal.class) {
            if (null == value) {
                return new BigDecimal(0);
            }
            return new BigDecimal(value + "");
        } else {
            return typeClass.cast(value);
        }
    }



    public static String removeLine(String str) {
        if (null != str && str.contains("_")) {
            int i = str.indexOf("_");
            char ch = str.charAt(i + 1);
            char newCh = (ch + "").substring(0, 1).toUpperCase().toCharArray()[0];
            String newStr = str.replace(str.charAt(i + 1), newCh);
            String newStr2 = newStr.replace("_", "");
            return newStr2;
        }
        return str;
    }


}
